using System;
using System.Threading;
using System.Net.Sockets;
using System.Windows.Forms;

public class LocalPort : IDisposable
{


	//====================================================================

	public event EstablishedConnectionEventHandler EstablishedConnection;
	public delegate void EstablishedConnectionEventHandler(string UserName, string UserAddress, UserConnection ExistingConnection);

	//====================================================================

	private Thread ListenerThread;
	private TcpListener Listener;

	//====================================================================

	#region " Constructors and destructors "

	public LocalPort()
	{
		ListenerThread = new Thread(DoListen);
		ListenerThread.Start();
	}

	public void Dispose()
	{
		if ((ListenerThread != null))
		{
			try {
				Listener.Stop();
				ListenerThread.Abort();
			}
			catch (Exception e) {
				// do nothing
			}
			ListenerThread = null;
		}
	}

	~LocalPort()
	{
		Dispose();
	}

	#endregion

	//====================================================================
	// Listening
	//====================================================================

	// This subroutine is used as a background listener thread to allow reading incoming
	// messages without lagging the user interface.
	private void DoListen()
	{
		try {
			// Start listen for new connections. 
			// Executes once when program started till its termination.
			Listener = new TcpListener(System.Net.IPAddress.Any, modMain.PortNum);

			// Once in program's lifetime
			Listener.Start();
		}

		catch (Exception e) {
			MessageBox.Show("Error initializing port listener: " + e.Message);
			return;
		}

		// Main loop of the Listener thread.
		while ((ListenerThread != null)) {
			try {
				// AcceptTcpClient waits till a new client knocks at the door (port)
				// and returns it.
				// UserConnection is a wrapper class for TcpClient.
				UserConnection NewUserConnection = new UserConnection(
					Listener.AcceptTcpClient(),
					ReceivedCallback);
			}

			catch (Exception e) {
				// We catch this when thread aborts
			}
		}
	}

	//====================================================================
	// Callback function of the Listener thread. The first message of every new incoming TcpClient
	// is received by this callback.
	//====================================================================

	private void ReceivedCallback(UserConnection Sender, string Data)
	{
		// Stop catching further messages from this client.
		Sender.LineReceived -= ReceivedCallback;

		//====================================================================
		// Data is expected to be in the following format:
		// CONNECT|UserName|UserAddress"
		// Parse the message.
		string[] Tokens = Data.Split('|');
		//     "|"c means char '|' in VB.NET

		if (Tokens.Length != 3 || Tokens[0] != modMain.msgConnect)
		{
			throw new Exception("Incorrect message received:" + Environment.NewLine + Data);
		}

		string Name = Tokens[1];
		string Address = Tokens[2];
		//====================================================================

		if (EstablishedConnection != null) {
			EstablishedConnection(Name, Address, Sender);
		}
	}
}
